<template>
  <div
      class="gantt"
      v-loading.fullscreen.lock="loading"
      element-loading-text="数据有点多，加载中，马上就好了"
  >
    <div class="legend">
      <i class="no-task" style="width: 20px; transform: translateX(-50px)"></i>
      <label style="transform: translateX(-30px)">空闲</label>
      <i class="plan" style="width: 20px"></i>
      <label>忙碌</label>
    </div>
    <el-table :data="mergedData" :span-method="mergeCells">
      <el-table-column
          v-for="(column, index) in columnsConfig"
          :key="index"
          width="130"
          v-bind="column"
      ></el-table-column>
      <el-table-column
          v-for="monthItem in monthData"
          :key="monthItem.month"
          align="center"
          min-width="80"
          :prop="monthItem.month"
          :label="monthItem.month"
      >
        <template #header>
          <span>{{ monthItem.month.substring(5) + "月" }}</span>
        </template>
        <el-table-column
            v-for="day in monthItem.dayArray"
            :key="day"
            align="center"
            :width="40"
            :prop="day"
        >
          <template #header>
 <span :class="{ 'weekend-header': isWeekend(day) }">{{
     day.substring(8)
   }}</span>
          </template>
          <template #default="scope">
            <div>
              <div :class="getTaskClass(scope.row.tasks, scope.column.property)">
                <template
                    v-if="
 scope.row.tasks.some((task) => {
 const planBegin = new Date(task[props.ganttConfig.planBeginColumn]);
 const planEnd = new Date(task[props.ganttConfig.planEndColumn]);
 const dayDate = new Date(scope.column.property);
 return dayDate >= planBegin && dayDate <= planEnd;
 })
 "
                >
                  <div>
                    {{
                      scope.row.tasks.find((task) => {
                        const planBegin = new Date(
                            task[props.ganttConfig.planBeginColumn]
                        );
                        const planEnd = new Date(task[props.ganttConfig.planEndColumn]);
                        const dayDate = new Date(scope.column.property);
                        return dayDate >= planBegin && dayDate <= planEnd;
                      }).description
                    }}
                  </div>
                </template>
              </div>
            </div>
          </template>
        </el-table-column>
      </el-table-column>
    </el-table>
  </div>
</template>

<script setup>
import {ref, onMounted} from "vue";

const props = defineProps({
  data: {
    type: Array,
    default: [],
  },
  columnsConfig: {
    type: Array,
    default: [],
  },
  loading: {
    type: Boolean,
    default: false,
  },
  ganttConfig: {
    type: Object,
    default: {
      planBeginColumn: "planBegin",
      planEndColumn: "planEnd",
      actualityBeginColumn: "actualityBegin",
      actualityEndColumn: "actualityEnd",
    },
  },
});
const monthData = ref({});
const mergedData = ref([]);
const tooltipVisible = ref(false);
const tooltipContent = ref("");
const tooltipPosition = ref({x: 0, y: 0});
// const loading = ref(props.loading);
function convertToDateString(dateStr) {
    // 将日期字符串解析为 Date 对象
    const dateObj = new Date(dateStr);

    // 检查日期对象是否有效
    if (isNaN(dateObj.getTime())) {
        throw new Error('Invalid date string');
    }

    // 获取年、月、日
    const year = dateObj.getFullYear();
    const month = String(dateObj.getMonth() + 1).padStart(2, '0'); // 月份从 0 开始，需要加 1
    const day = String(dateObj.getDate()).padStart(2, '0');

    // 返回格式化的日期字符串
    return `${year}-${month}-${day}`;
}
const getNonOverlappingTimeRanges = (tasks) => {

  const intervals = [];
  const mergedIntervals = [];
  // 收集所有任务的时间区间
  tasks.forEach((task) => {
    const start = new Date(task[props.ganttConfig.planBeginColumn]);
    const end = new Date(task[props.ganttConfig.planEndColumn]);
    intervals.push({start, end});
  });
  // 按开始时间排序
  intervals.sort((a, b) => a.start - b.start);
  let currentStart = intervals[0].start;
  let currentEnd = intervals[0].end;
  let nonOverlappingStart = null;
  let nonOverlappingEnd = null;

  // 合并重叠的时间区间
  // const mergeIntervals = (intervals) => {
  //   for (let i = 0; i < intervals.length-1; i++) {
  //     // const {start, end} = intervals[i];
  //     const currentRange = intervals[i];
  //     const nextRange = intervals[i + 1];
  //     const currentEnd = new Date(currentRange.end);
  //     const nextStart = new Date(nextRange.start);
  //
  //     // console.log("---------------343--------",currentEnd,nextStart)
  //     if (nextStart < currentEnd){
  //        // 创建起始日期对象
  //       var startDate = nextRange.end;
  //       // 创建目标日期对象
  //       var targetDate = new Date(currentEnd);
  //       // 检查是否需要增加一天
  //       if (startDate => targetDate) {
  //         // 如果起始日期比目标日期晚一天，那么需要在目标日期上加一天
  //         targetDate.setDate(targetDate.getDate() + 1);
  //       } else if (startDate <= targetDate) {
  //         // 如果起始日期比目标日期早一天，那么需要在目标日期上减一天
  //         targetDate.setDate(targetDate.getDate() - 1);
  //       }
  //         // console.log("---------------开始日期小于结束日期--------",convertToDateString(targetDate),convertToDateString(startDate))
  //       nonOverlappingStart = new Date(targetDate.toUTCString());
  //       nonOverlappingEnd = new Date(startDate);
  //       mergedIntervals.push({start: nonOverlappingStart, end: nonOverlappingEnd});
  //     }
  //     else {
  //       nonOverlappingStart = targetDate;
  //       nonOverlappingEnd = startDate;
  //       mergedIntervals.push({start: nextStart, end: nextRange.end});
  //       // console.log("---------------开始日期大于结束日期--------",convertToDateString(nextStart),convertToDateString(nextRange.end))
  //   }
  //     // 提取目标日期的日份数
  //   }
  // };
  // mergeIntervals(intervals);
  for (let i = 0; i < intervals.length-1; i++) {
      // const {start, end} = intervals[i];
      const currentRange = intervals[i];
      const nextRange = intervals[i + 1];
      const currentEnd = new Date(currentRange.end);
      const nextStart = new Date(nextRange.start);
      // console.log("---------------343--------",currentEnd,nextStart)
      if (nextStart < currentEnd){
         // 创建起始日期对象
        var startDate = nextRange.end;
        // 创建目标日期对象
        var targetDate = new Date(currentEnd);
        // 检查是否需要增加一天
        if (startDate => targetDate) {
          // 如果起始日期比目标日期晚一天，那么需要在目标日期上加一天
          targetDate.setDate(targetDate.getDate() + 1);
        } else if (startDate <= targetDate) {
          // 如果起始日期比目标日期早一天，那么需要在目标日期上减一天
          targetDate.setDate(targetDate.getDate() - 1);
        }
          // console.log("---------------开始日期小于结束日期--------",convertToDateString(targetDate),convertToDateString(startDate))
          nonOverlappingStart = new Date(targetDate.toUTCString());
          nonOverlappingEnd = new Date(startDate);
        mergedIntervals.push({start: nonOverlappingStart, end: nonOverlappingEnd});

      }
      else {
          nonOverlappingStart = targetDate;
          nonOverlappingEnd = startDate;
        mergedIntervals.push({start: nextStart, end: nextRange.end});
      }

    }
   return mergedIntervals;
};
function *data(dictlit){
  for (const dict of dictlit){
    yield dict;
  }
}
/**
 合并单元格
 */
const mergeCells = ({ row, column }) => {
  const day = column.property;
  const dayDate = new Date(day);
  const tasks = row.tasks;

  // 查找当天所有重叠的任务
  const overlappingTasks = tasks.filter((task) => {
    const planBegin = new Date(task[props.ganttConfig.planBeginColumn]);
    const planEnd = new Date(task[props.ganttConfig.planEndColumn]);
    return dayDate >= planBegin && dayDate <= planEnd;
  });

  // 如果有重叠任务
  if (overlappingTasks.length > 0) {
    const firstTask = overlappingTasks[0];
    const planBegin = new Date(firstTask[props.ganttConfig.planBeginColumn]);
    const planEnd = new Date(firstTask[props.ganttConfig.planEndColumn]);
    const mergedIntervals = getNonOverlappingTimeRanges(tasks);
    const overlappingRange = mergedIntervals.find(interval => {
      return dayDate >= interval.start && dayDate <= interval.end;
    });

    let startDate = undefined;
    let endDate = undefined;

    if (overlappingRange) {
      startDate = new Date(overlappingRange.start);
      endDate = new Date(overlappingRange.end);
    }

    if (dayDate.toDateString() === planBegin.toDateString()) {
      const dayCount = Math.ceil((planEnd - planBegin) / (1000 * 60 * 60 * 24)) + 1;
      return {
        rowspan: 1,
        colspan: dayCount,
      };
    } else if (startDate && endDate) {
      if (dayDate.toDateString() === startDate.toDateString()) {
        const dayCount = Math.ceil((endDate - startDate) / (1000 * 60 * 60 * 24)) + 1;
        return { rowspan: 1, colspan: dayCount };
      }else {
        return { rowspan: 0, colspan: 0 };
      }
    }else {
      return { rowspan: 0, colspan: 0 };
    }
  }

  // 没有重叠任务的情况下
  return { rowspan: 1, colspan: 1 }; // 无任务的日期
}


/**
 * 初始化甘特图的日期范围和月份数据
 */
const init = () => {
  console.log("初始化看图了");
  // let minDate = new Date(2024, 1, 1);
  mergedData.value = [];
  monthData.value = {};
  let today = new Date();
  let minDate = new Date(today.getFullYear(), today.getMonth(), 1);
  // let maxDate = new Date(2024, 1, 27);
  let maxDate = new Date(today.getFullYear(), today.getMonth() + 1, 0);

  // 处理数据，计算最小和最大日期
  props.data.forEach((person) => {
    person.task.forEach((task) => {
      const planBegin = new Date(task[props.ganttConfig.planBeginColumn]);
      const planEnd = new Date(task[props.ganttConfig.planEndColumn]);
      const actualityBegin = task[props.ganttConfig.actualityBeginColumn]
          ? new Date(task[props.ganttConfig.actualityBeginColumn])
          : null;
      const actualityEnd = task[props.ganttConfig.actualityEndColumn]
          ? new Date(task[props.ganttConfig.actualityEndColumn])
          : null;

      minDate = !minDate || planBegin < minDate ? planBegin : minDate;
      maxDate = !maxDate || planEnd > maxDate ? planEnd : maxDate;
      if (actualityBegin && (!minDate || actualityBegin < minDate))
        minDate = actualityBegin;
      if (actualityEnd && (!maxDate || actualityEnd > maxDate)) maxDate = actualityEnd;
    });
  });
  // 处理边界日期
  minDate = new Date(minDate.getTime() - 1 * 24 * 60 * 60 * 1000);
  maxDate = new Date(maxDate.getTime() + 30 * 24 * 60 * 60 * 1000);

  // 生成月份和天数数组
  let current = new Date(format(minDate));
  while (!isAfter(current, maxDate)) {
    const month = formatYearMonth(current);
    const day = format(current);
    if (!monthData.value[month]) {
      monthData.value[month] = {month, dayArray: []};
    }
    monthData.value[month].dayArray.push(day);
    current = after(current);
  }

  // 合并数据，准备渲染
  mergedData.value = props.data.map((person) => ({
    ...person,
    tasks: person.task
        .map((task) => ({
          ...task,
          description: task.description || "未命名任务",
        }))
        .filter((task) => task.description),
  }));
};
/**
 * 格式化日期为 YYYY-MM-DD
 */
const format = (date) => {
  const day = String(date.getDate()).padStart(2, "0");
  return `${formatYearMonth(date)}-${day}`;
};

const formatYearMonth = (date) => {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, "0");
  return `${year}-${month}`;
};

const after = (date) => new Date(date.getTime() + 24 * 60 * 60 * 1000);
const isAfter = (date1, date2) => date1.getTime() >= date2.getTime();

const isWeekend = (day) => {
  const dayDate = new Date(day);
  return dayDate.getDay() === 0 || dayDate.getDay() === 6; // 0: Sunday, 6: Saturday
};

const showTooltip = (tasks, day, event) => {
  const dayDate = new Date(day);
  const task = tasks.find((task) => {
    const planBegin = new Date(task[props.ganttConfig.planBeginColumn]);
    const planEnd = new Date(task[props.ganttConfig.planEndColumn]);
    return dayDate >= planBegin && dayDate <= planEnd;
  });
  if (task) {
    tooltipContent.value = task.description;
    tooltipVisible.value = true;
    tooltipPosition.value = {x: event.clientX + 10, y: event.clientY + 10};
  } else {
    hideTooltip();
  }
};

const hideTooltip = () => {
  tooltipVisible.value = false;
};

/**
 * 获取任务样式
 */
const getTaskClass = (tasks, day) => {
  const dayDate = new Date(day);
  const isWeekend = dayDate.getDay() === 0 || dayDate.getDay() === 6; // 判断是否是周末
  const hasTask = tasks.some((task) => {
    const planBegin = new Date(task[props.ganttConfig.planBeginColumn]);
    const planEnd = new Date(task[props.ganttConfig.planEndColumn]);
    const actualityBegin = task[props.ganttConfig.actualityBeginColumn]
        ? new Date(task[props.ganttConfig.actualityBeginColumn])
        : null;
    const actualityEnd = task[props.ganttConfig.actualityEndColumn]
        ? new Date(task[props.ganttConfig.actualityEndColumn])
        : null;

    return (
        (dayDate >= planBegin && dayDate <= planEnd) ||
        (actualityBegin &&
            actualityEnd &&
            dayDate >= actualityBegin &&
            dayDate <= actualityEnd)
    );
  });

  if (hasTask) {
    for (const task of tasks) {
      const planBegin = new Date(task[props.ganttConfig.planBeginColumn]);
      const planEnd = new Date(task[props.ganttConfig.planEndColumn]);
      const actualityBegin = task[props.ganttConfig.actualityBeginColumn]
          ? new Date(task[props.ganttConfig.actualityBeginColumn])
          : null;
      const actualityEnd = task[props.ganttConfig.actualityEndColumn]
          ? new Date(task[props.ganttConfig.actualityEndColumn])
          : null;

      if (dayDate >= planBegin && dayDate <= planEnd) {
        return "plan"; // 在计划范围内
      }
      // if (actualityBegin && actualityEnd && dayDate >= actualityBegin && dayDate <= actualityEnd) {
      // return 'actuality'; // 在实际范围内
      // }
    }
  } else if (!isWeekend) {
    return "no-task"; // 无任务且不是周末
  }

  return "empty"; // 不在任何任务范围内
};
// 在组件挂载时初始化数据
// onMounted(() => {
// init();
// });
watchEffect(() => {
  init();
});
</script>

<style scoped>
.plan {
  display: flex;
  height: 20px;
  background-color: #ffa500;
  margin: 0 -12px;
  color: antiquewhite;
}

.weekend-header {
  color: red;
  font-weight: bold;
}

.empty {
  display: flex;
  width: calc(100% + 24px);
  height: 16px;
  margin: 0 -12px;
}

.legend {
  display: flex;
  line-height: 40px;
  flex-direction: row;
  justify-content: right;
  align-items: center;
  padding: 0 20px;

  * {
    margin: 0 5px;
  }

  i {
    width: 5px;
    height: 16px;
  }
}

.no-task {
  display: flex;
  width: 37px;
  height: 16px;
  background-color: #bfefd4; /* 你可以根据需要选择颜色 */
  margin: 0 -12px;
}

.tooltip {
  position: absolute;
  left: var(--tooltip-x); /* 根据 JavaScript 动态设置 */
  top: var(--tooltip-y); /* 根据 JavaScript 动态设置 */
  opacity: 1;
  background-color: rgba(0, 0, 0, 0.9);
  color: white;
  padding: 8px;
  border-radius: 4px;
  z-index: 9999; /* 设置为更高的值 */
  pointer-events: none; /* 防止 tooltip 影响鼠标事件 */
  transition: opacity 0.3s; /* 添加渐变效果 */
  /* 其他样式 */
}

.overlapping-task {
  background-color: rgba(255, 0, 0, 0.5); /* 红色背景 */
}

.main-task {
  background-color: rgba(0, 255, 0, 0.5); /* 绿色背景 */
}

.sub-task {
  background-color: rgba(255, 255, 0, 0.5); /* 黄色背景 */
}
</style>